package com.hua.api.modules.home.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.service.WxPayService;
import com.hua.api.core.activemq.consumer.event.EventConstant;
import com.hua.api.core.activemq.consumer.event.TemplateIdConstant;
import com.hua.api.core.constants.Status;
import com.hua.api.core.framework.config.WxMaConfiguration;
import com.hua.api.core.framework.util.DateUtil;
import com.hua.api.core.framework.util.exception.ApiError;
import com.hua.api.core.util.StringUtil;
import com.hua.api.core.util.ValidationUtil;
import com.hua.api.modules.home.dao.MemberInfoDao;
import com.hua.api.modules.home.domain.MemberInfo;
import com.hua.api.modules.home.domain.MemberSubscribeTemplate;
import com.hua.api.modules.home.service.MessageService;
import com.hua.api.modules.order.dao.OrderInfoDao;
import com.hua.api.modules.order.domain.OrderInfo;
import com.hua.api.modules.order.domain.OrderItems;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service("wxMessageService")
@RequiredArgsConstructor
public class WxMessageServiceImpl implements MessageService {

    private final WxMaService wxMaService;

    private final WxPayService wxPayService;

    private final OrderInfoDao orderInfoDao;

    private final MemberInfoDao memberInfoDao;

    private final WxMaConfiguration wxMaConfiguration;


    // 微信小程序消息推送。
    private void sendMessageUseTemplateid(String templateId,Map<String,String> map,String openId){

        try {
            List<WxMaSubscribeMessage.MsgData> data = new ArrayList<>();
            for(Map.Entry<String,String> en:map.entrySet()){
                WxMaSubscribeMessage.MsgData msgData = new WxMaSubscribeMessage.MsgData(en.getKey(),en.getValue());
                data.add(msgData);
            }

            WxMaSubscribeMessage subscribeMessage = WxMaSubscribeMessage
                    .builder()
                    .templateId(templateId)
                    .data(data)
                    .page("pages/tabbar/index/index")
                    .toUser(openId)
                    .build();

            wxMaService.getSubscribeService().sendSubscribeMsg(subscribeMessage);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
    }

    private String getTemplateId(String event){
        if(StringUtil.equals(EventConstant.event_order_created,event)){
            return TemplateIdConstant.order_created_template_id;
        }
        return null;
    }

    private Map<String,String> getData(String event,OrderInfo orderInfo){
        if(StringUtil.equals(EventConstant.event_order_created,event)){
            Map<String,String> map = new HashMap<>();
            /**
             * 订单编号  {{character_string7.DATA}}
             * 商品名称  {{thing10.DATA}}
             * 交易金额  {{amount1.DATA}}
             * 支付时间  {{time8.DATA}}
             * 订单状态  {{phrase11.DATA}}
             * */
            List<OrderItems> list = orderInfoDao.queryOrderItems(orderInfo.getId());
            String goodsName ="";
            if (list.size()>0){
                goodsName = list.get(0).getFoodName();
                if(list.size()>1){
                    goodsName+="（等"+list.size()+"件）";
                }
            }
            map.put("character_string7",orderInfo.getOrderNo());
            map.put("thing10",goodsName);
            map.put("amount1",NumberUtil.decimalFormatMoney(orderInfo.getTotal()));
            map.put("time8",DateUtil.getFormatDate(orderInfo.getCtime(),"yyyy-MM-dd HH:mm:ss"));
            Status.OrderStatus status = Status.OrderStatus.fromValue(orderInfo.getStatus());
            map.put("phrase11",status.getName());
            return map;
        }

        return null;
    }

    // 小程序发货通知
    // https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#%E4%B8%80%E3%80%81%E5%8F%91%E8%B4%A7%E4%BF%A1%E6%81%AF%E5%BD%95%E5%85%A5%E6%8E%A5%E5%8F%A3
    public void uploadWechatShippingInfo(OrderInfo orderInfo, List<OrderItems> items, MemberInfo m,JSONObject data){
        log.info("uploadWechatShippingInfo data={}",data.toJSONString());
        // {"order_no":"911748225758204002","shipperPhone":"18698680928","shipperName":"尹丹丹"}
        List<ShippingListBean> shippingList = new ArrayList<>();
        String logisticsTypeData = data.getString("logisticsType");
        Integer logisticsType;
        Integer deliveryMode = 1;
        String openId=m.getOpenUid();
        if(StringUtil.equals(logisticsTypeData,"1")){
            // 实体物流配送采用快递公司进行实体物流配送形式 待完善...
            logisticsType = 1;

        }else if(StringUtil.equals(logisticsTypeData,"3")) {
            // 虚拟商品，虚拟商品，待完善...
            logisticsType = 3;

        }else{
            // 默认
            logisticsType = 2;
            // String shipperName = data.getString("shipperName");
            String shipperPhone = data.getString("shipperPhone");
            ShippingListBean shipping = new ShippingListBean();
            shipping.setTrackingNo(shipperPhone); //自配送单号 手机号当作单号
            String itemDesc = "";
            if(items.size()>0){
                itemDesc = items.get(0).getFoodName();
            }
            if(items.size()>1){
                itemDesc+=("("+items.size()+")");
            }
            shipping.setItemDesc(itemDesc);  // 商品名称
            shipping.setTrackingNo(shipperPhone); // 手机号当物流单号
            shipping.setExpressCompany("商家自配");
            shippingList.add(shipping);

        }

        if(StringUtil.isEmpty(openId)){
            log.error("WxMessageServiceImpl.uploadWechatShippingInfo(openId为空无法调用发货接口 orderNo={},logisticsType={},deliveryMode={},openId={})",orderInfo.getOrderNo(),logisticsType,deliveryMode,openId);
            throw ApiError.Type.LOGIC_ERROR.toException("openId is empty");
        }
        log.info("WxMessageServiceImpl.uploadWechatShippingInfo(微信订单发货 orderNo={},logisticsType={},deliveryMode={},openId={})",orderInfo.getOrderNo(),logisticsType,deliveryMode,openId);
        
        OrderKeyBean orderKeyBean = new OrderKeyBean();
        orderKeyBean.setOrderNumberType(1); // 订单单号类型，用于确认需要上传详情的订单。枚举值 1，使用下单商户号和商户侧单号；枚举值2，使用微信支付单号。
        orderKeyBean.setOutTradeNo(orderInfo.getOrderNo());
        orderKeyBean.setMchId(wxMaConfiguration.mchId);
        PayerBean payerBean = new PayerBean();
        payerBean.setOpenid(openId);

        WxMaOrderShippingInfoUploadRequest request = WxMaOrderShippingInfoUploadRequest.builder()
                .orderKey(orderKeyBean)
                .payer(payerBean)
                .shippingList(shippingList)
                .logisticsType(logisticsType) // 物流模式，发货方式枚举值：1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品，虚拟商品，例如话费充值，点卡等，无实体配送形式 4、用户自提
                .deliveryMode(deliveryMode) // 发货模式，发货模式枚举值：1、UNIFIED_DELIVERY（统一发货）2、SPLIT_DELIVERY（分拆发货） 示例值: UNIFIED_DELIVERY
                .isAllDelivered(true) // 分拆发货模式时必填，用于标识分拆发货模式下是否已全部发货完成，只有全部发货完成的情况下才会向用户推送发货完成通知。示例值: true/false
                .build();
        
        // 订单，需要上传物流信息的订单
        // orderKeyBean.setOrderNumberType();
        request.setOrderKey(orderKeyBean);
        //WxMaOrderShippingService wxMaOrderShippingService =new WxMaOrderShippingServiceImpl(wxMaService);

        try {
            log.info("wxMaOrderShippingService.upload()");
            // wxMaOrderShippingService.upload(request);
            WxMaOrderShippingInfoBaseResponse response = wxMaService.getWxMaOrderShippingService().upload(request);
            log.info("response={}",response.toString());
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }


    }


    // 小程序消息订阅
    @Override
    public void sendMessage(JSONObject data,String event) {
        if(StringUtil.equals(EventConstant.event_order_created,event)){
            // 订单创建
            onOrderCreated(data);
        }else if(StringUtil.equals(EventConstant.event_logistics_start,event)){
            // 开始配送
            onLogisticsStart(data);
        }
    }

    private void onOrderCreated(JSONObject data){
        String orderNo = data.getString("order_no");
        ValidationUtil.requireNotNull(orderNo,"订单号不存在！");
        OrderInfo orderInfo = orderInfoDao.findOrderInfoWithOrderNo(orderNo);
        ValidationUtil.requireNotNull(orderInfo,"订单数据不存在！");

        if(StringUtil.equals(Status.SOURCE_WECHAT,orderInfo.getSource())){
            String templateId = getTemplateId(EventConstant.event_order_created);
            ValidationUtil.requireNotNull(templateId,"订单号不存在！");
            MemberInfo member = orderInfoDao.getObject(MemberInfo.class,orderInfo.getUserId());
            ValidationUtil.requireNotNull(member,"会员信息不存在！");
            MemberSubscribeTemplate template = memberInfoDao.findMemberSubscribeTemplate(orderInfo.getUserId(),templateId);
            if(template==null){
                log.warn("消息未订阅 userId={},templateId={}",orderInfo.getUserId(),TemplateIdConstant.order_created_template_id);
            }else if(StringUtil.equals(template.getStatus(),"accept")){
                log.info("小程序消息推送 templateId={},orderNo={},event={}",templateId,orderNo,EventConstant.event_order_created);
                Map<String,String> msgData = getData(EventConstant.event_order_created,orderInfo);
                sendMessageUseTemplateid(templateId,msgData,member.getOpenUid());
            }else {
                log.warn("消息禁止推送 status={}",template.getStatus());
            }
        }else {
            log.warn("非微信小程序的订单无需推送 orderNo={}",orderNo);
        }
    }



    // 开始配送
    public void onLogisticsStart(JSONObject data){
        log.info("WxMessageServiceImpl.onLogisticsStart() data={}",data.toJSONString());
        String orderNo = data.getString("order_no");
        ValidationUtil.requireNotNull(orderNo,"订单号不存在！");
        OrderInfo orderInfo = orderInfoDao.findOrderInfoWithOrderNo(orderNo);
        ValidationUtil.requireNotNull(orderInfo,"订单数据不存在！");
        List<OrderItems> items = orderInfoDao.queryOrderItems(orderInfo.getId());
        MemberInfo memberInfo = orderInfoDao.getObject(MemberInfo.class, orderInfo.getUserId());
        ValidationUtil.requireNotNull(memberInfo,"订单用户不存在！");
        if(StringUtil.equals(Status.SOURCE_WECHAT,orderInfo.getSource())){
            log.info("上传微信物流信息开始");
            // 微信商城 发货操作
            uploadWechatShippingInfo(orderInfo, items,memberInfo, data);

        }else {
            log.warn("非微信渠道，无需上传物流信息 orderNo={}",orderNo);
        }
    }

}
